package com.bonc.rms.service.impl.tms;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.bonc.odk.logmanager.LogManager;
import com.bonc.rms.dao.tms.EmployeeDimissionDao;
import com.bonc.rms.service.tms.EmployeeDimissionService;
import com.bonc.rms.service.tms.ISalaryRecordService;
import com.bonc.rms.service.tms.ISalaryService;
import com.bonc.rms.utils.CalendarUtil;

@Service
@Transactional
public class EmployeeDimissionServiceImpl implements EmployeeDimissionService{

    @Autowired
	EmployeeDimissionDao employeeDimissionDao;
    @Autowired
    ISalaryService salaryService;
    @Autowired
    ISalaryRecordService salaryRecordService;
    
    @Override
    public List<Map<String, Object>> getShortDimissionEmployee(Integer departmentId, Integer pageNum, Integer pageSize) {
    	LogManager.Method("In  Service : EmployeeDimissionServiceImpl -> getShortDimissionEmployee");
		LogManager.Method("Out Service : EmployeeDimissionServiceImpl -> getShortDimissionEmployee");
		return employeeDimissionDao.getShortDimissionEmployee(departmentId, pageNum, pageSize);
    }

    @Override
    public List<Map<String, Object>> getDepartmentWages(
    		Integer buId, 
    		Integer departmentId, 
    		String startDate, 
    		String endDate, 
    		Integer pageNum, 
    		Integer pageSize
    	) {
    	LogManager.Method("In  Service : EmployeeDimissionServiceImpl -> getDepartmentWages");
    	List<Integer> depIdList = employeeDimissionDao.getDepartmentWages(departmentId, pageNum, pageSize );
    	List<Map<String, Object>> retData = new ArrayList<>();
    	for(Integer depId : depIdList) {
    		retData.add(getDepartmentWages(depId, startDate, endDate));
    	}
    	LogManager.Method("Out Service : EmployeeDimissionServiceImpl -> getDepartmentWages");
    	return retData;
    }
    
    private Map<String, Object> getDepartmentWages(
    		Integer departmentId, 
    		String startDate, 
    		String endDate
    	) {
    	LogManager.Method("In  Service : EmployeeDimissionServiceImpl -> getDepartmentWages");
    	int depNum = employeeDimissionDao.getDepNum(departmentId);
    	List<Map<String, Object>> depNameList = employeeDimissionDao.getDepName(departmentId);
    	String depName = null;
    	if(depNameList != null && depNameList.size() > 0) {
    		depName = (String) depNameList.get(0).get("name");
    	}
        List<Object> jobNumberList = employeeDimissionDao.getEmployeeJobNumber(departmentId);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Date startMonthDate = null;
        Date endMonthDate = null;
        java.sql.Date startMonthDateSql = null;
        java.sql.Date endMonthDateSql = null;
        try {
            startMonthDate = sdf.parse(startDate);
            endMonthDate = sdf.parse(endDate);
            startMonthDateSql = new java.sql.Date(startMonthDate.getTime());
            endMonthDateSql = new java.sql.Date(endMonthDate.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        
        Calendar startDateCal = CalendarUtil.convertToCal(startDate);
        Calendar endDateCal = CalendarUtil.convertToCal(endDate);
        
        dealDate(startDateCal, endDateCal);
        
        double salaryAve = 0.0;
        double salaryTotal = 0.0;
        double socialSecurityBenefitsCostTotal = 0;
        double humanResourceCostTotal = 0.0;
        
        for(Object jobNumber : jobNumberList) {
            
            List<Map<String, Object>> salaryRecordList = 
                    salaryRecordService.getSalaryRecordByJobNumberAndBetweenDate(
                            (String) jobNumber, 
                            startMonthDateSql, 
                            endMonthDateSql
                        );
            
            List<Map<String, Object>> salaryRecordBeforeList = 
                    salaryRecordService.getSalaryRecordByJobNumberAndBeforeDate(
                            (String) jobNumber, 
                            startMonthDateSql
                        );
            
            double humanResourceCost = 0.0;

            double adjustedBasicWage = 0.0;
            double adjustedPerformance = 0.0;
            double adjustedBonus = 0.0;
            double salary = 0.0;
            
            if(salaryRecordBeforeList.size() > 0) {
                Map<String, Object> lastSalaryRecordBefore = salaryRecordBeforeList.get(salaryRecordBeforeList.size() - 1);
                adjustedBasicWage = ((BigDecimal) lastSalaryRecordBefore.get("adjusted_basic_wage")).doubleValue();
                adjustedPerformance = ((BigDecimal)  lastSalaryRecordBefore.get("adjusted_performance")).doubleValue();
                adjustedBonus = ((BigDecimal) lastSalaryRecordBefore.get("adjusted_bonus")).doubleValue();
                salary = adjustedBasicWage + adjustedPerformance + adjustedBonus;
                
                humanResourceCost = ((BigDecimal) lastSalaryRecordBefore.get("adjusted_human_resource_cost")).doubleValue();
            } else {
                List<Map<String, Object>> salaryList = salaryService.getSalaryByJobNumber((String) jobNumber);
                if(salaryList.size() > 0) {
                    Map<String, Object> initSalary = salaryList.get(0);
                    adjustedBasicWage = ((BigDecimal) initSalary.get("basic_wage")).doubleValue();
                    adjustedPerformance = ((BigDecimal)  initSalary.get("performance")).doubleValue();
                    adjustedBonus = ((BigDecimal)  initSalary.get("bonus")).doubleValue();
                    salary = adjustedBasicWage + adjustedPerformance + adjustedBonus;
                    
                    humanResourceCost = ((BigDecimal)  initSalary.get("human_resource_cost")).doubleValue();
                }
            }
            
            double salarySum = 0.0;
            if(salaryRecordList.size() > 0) {
                // 发生调薪

                Map<String, Object> map = null;
                Calendar calTemp = Calendar.getInstance();
                calTemp.setTime(startMonthDate);
                for(int i = 0 ; i < salaryRecordList.size(); i ++) {
                    // 统计前几段时间内的工资
                    map = salaryRecordList.get(i);
                    java.sql.Timestamp adjustDate = (java.sql.Timestamp) map.get("adjust_date");
                    Calendar adjustDateCal = Calendar.getInstance();
                    adjustDateCal.setTime(adjustDate);
                    
                    salarySum += salary * CalendarUtil.calMonthDif(calTemp, adjustDateCal);
                    humanResourceCostTotal += humanResourceCost;
                    
                    calTemp.setTime(adjustDate);
                    adjustedBasicWage = ((BigDecimal) map.get("adjusted_basic_wage")).doubleValue();
                    adjustedPerformance = ((BigDecimal) map.get("adjusted_performance")).doubleValue();
                    adjustedBonus = ((BigDecimal) map.get("adjusted_bonus")).doubleValue();
                    salary = adjustedBasicWage + adjustedPerformance + adjustedBonus;
                    
                    humanResourceCost = ((BigDecimal) map.get("adjusted_human_resource_cost")).doubleValue();
                }
                
                // 统计最后一段时间内的工资
                map = salaryRecordList.get(salaryRecordList.size() - 1);
                java.sql.Timestamp adjustDate = (java.sql.Timestamp) map.get("adjust_date");
                calTemp.setTime(adjustDate);
                salarySum += salary * (CalendarUtil.calMonthDif(calTemp, endDateCal) + 1);
                
                // 统计前几段时间内人力成本
                
            } else {
                // 未发生调薪
                salarySum = salary * CalendarUtil.calMonthDif(startDateCal, endDateCal);
                humanResourceCostTotal = humanResourceCost * CalendarUtil.calMonthDif(startDateCal, endDateCal);
            }
            
            salaryTotal += salarySum;
            socialSecurityBenefitsCostTotal += salarySum * 0.51 * 0.392;
        }
        salaryAve = salaryTotal / jobNumberList.size();
        
        DecimalFormat df =(DecimalFormat) NumberFormat.getInstance();
        df.setMaximumFractionDigits(2);
        
        Map<String, Object> retMap = new HashMap<String, Object>();
        retMap.put("salaryTotal", df.format(salaryTotal));
        retMap.put("socialSecurityBenefitsCostTotal", df.format(socialSecurityBenefitsCostTotal));
        retMap.put("salaryAve", df.format(salaryAve));
        retMap.put("humanResourceCost", df.format(humanResourceCostTotal));
        retMap.put("depName", depName);
        retMap.put("depNum", depNum);
        LogManager.Method("Out Service : EmployeeDimissionServiceImpl -> getDepartmentWages");
		return retMap;
    }

    private void dealDate(Calendar startMonth, Calendar endMonth) {
    	LogManager.Method("In  Service : EmployeeDimissionServiceImpl -> dealDate");
		if(startMonth != null) {
            startMonth.set(Calendar.DAY_OF_MONTH, 1);
        }
        
        if(endMonth != null) {
            endMonth.set(Calendar.DAY_OF_MONTH, endMonth.getActualMaximum(Calendar.DAY_OF_MONTH));
        }
        LogManager.Method("Out Service : EmployeeDimissionServiceImpl -> dealDate");
	}
    
	@Override
	public int getTotalNumber(Integer departmentId) {
		LogManager.Method("In  Service : EmployeeDimissionServiceImpl -> getTotalNumber");
		LogManager.Method("Out Service : EmployeeDimissionServiceImpl -> getTotalNumber");
		return employeeDimissionDao.getTotalNumber(departmentId);
	}

	@Override
	public int getTotalDepNumber(Integer departmentId) {
		LogManager.Method("In  Service : EmployeeDimissionServiceImpl -> getTotalDepNumber");
		LogManager.Method("Out Service : EmployeeDimissionServiceImpl -> getTotalDepNumber");
		return employeeDimissionDao.getTotalDepNumber(departmentId);
	}
    
}
